import 'dart:convert' show json;
import 'package:x3_base_core/base_models/base_model_asT.dart';
import 'package:x3_base_core/base_utils/base_transform_util.dart';
import 'package:x3_base_core/base_models/base_key_value_model.dart';
import 'package:x3_base_core/base_enums/base_http_show_type_enum.dart';
import 'package:x3_base_core/base_enums/base_http_input_type_enum.dart';
import 'package:x3_base_core/base_enums/base_http_access_model_enum.dart';

import 'base_http_result_model.dart';

class BaseHttpRequestModel {
  /// 名称 对应数据库的列名称
  String fieldName;

  /// 显示名称
  String name;

  /// 提示内容
  String notes;

  /// 是否必填
  bool required;

  /// 访问模式(只读 读写)
  BaseHttpAccessModelEnum accessMode;

  /// 请求的服务地址  inputApi 与 dioX2Util 不可以共存
  String inputApi;

  /// 输入的类型
  BaseHttpInputTypeEnum inputType;

  /// 显示类型
  BaseHttpShowTypeEnum showType;

  /// 默认值
  String defaultValue;

  /// 数值
  String value;

  /// 跳转地址
  String webUrl;

  /// 正则校验
  String inputRegex;

  /// 包含的数据  用于下拉列表数据 避免再次请求服务获取
  List<BaseKeyValueModel> selectData;

  /// label 宽度
  double labelWidth;

  /// 最小值
  dynamic min;

  /// dio请求得到数据
  /// ⚠️ inputApi 与 dioX2Util 不可以共存
  /// ⚠️ dioX2Util 与 dealWithResult 必须同时 不为空
  Future<BaseHttpResultModel> dioX2Util;

  /// 请求结果数据处理 不固定类型 方便其他类型的调用
  dynamic Function(BaseHttpResultModel resultModel) dealWithResult;

  /// 其他参数 - 后续追加的非通用参数全部放到这里
  Map<String, dynamic> otherParam;

  BaseHttpRequestModel({
    this.fieldName,
    this.name,
    this.notes,
    this.required,
    this.accessMode,
    this.inputApi,
    this.inputType,
    this.showType,
    this.defaultValue,
    this.value,
    this.webUrl,
    this.inputRegex,
    this.selectData,
    this.labelWidth,
    this.min,
    this.dioX2Util,
    this.dealWithResult,
    this.otherParam,
  });

  factory BaseHttpRequestModel.defaultCreate({
    String fieldName,
    String name,
    String notes,
    bool required,
    BaseHttpAccessModelEnum accessMode = BaseHttpAccessModelEnum.WebReadWrite,
    BaseHttpInputTypeEnum inputType,
    BaseHttpShowTypeEnum showType = BaseHttpShowTypeEnum.Text,
  }) {
    return BaseHttpRequestModel(
      fieldName: fieldName,
      name: name,
      notes: notes,
      required: required,
      accessMode: accessMode,
      inputType: inputType,
      showType: showType,
    );
  }

  factory BaseHttpRequestModel.fromJson(Map<String, dynamic> jsonRes) {
    if (jsonRes == null) {
      return null;
    }

    // 是否必填
    bool isRequired = asT<bool>(jsonRes['required']);

    /// 下拉选择数据
    final List<BaseKeyValueModel> selectData = jsonRes['selectData'] is List ? <BaseKeyValueModel>[] : null;
    if (selectData != null) {
      if (!isRequired) selectData.add(BaseKeyValueModel(key: null, value: ''));
      for (final dynamic item in jsonRes['selectData']) {
        if (item != null) {
          selectData.add(BaseKeyValueModel.fromJson(asT<Map<dynamic, dynamic>>(item)));
        }
      }
    }

    /// AccessMode 赋值
    BaseHttpAccessModelEnum accessMode;
    if (jsonRes['accessMode'] != null && jsonRes['accessMode'].toString().isNotEmpty) {
      accessMode = BaseTransformUtil.enumFromString(BaseHttpAccessModelEnum.values, jsonRes['accessMode']);
    }

    /// inputType 赋值
    BaseHttpInputTypeEnum inputType;
    if (jsonRes['inputType'] != null && jsonRes['inputType'].toString().isNotEmpty) {
      inputType = BaseTransformUtil.enumFromString(BaseHttpInputTypeEnum.values, jsonRes['inputType']);
    }

    /// showType 赋值
    BaseHttpShowTypeEnum showType;
    if (jsonRes['showType'] != null && jsonRes['showType'].toString().isNotEmpty) {
      showType = BaseTransformUtil.enumFromString(BaseHttpShowTypeEnum.values, jsonRes['showType']);
    }

    return BaseHttpRequestModel(
      fieldName: asT<String>(jsonRes['fieldName']),
      name: asT<String>(jsonRes['name']),
      notes: asT<String>(jsonRes['notes']),
      required: isRequired,
      accessMode: accessMode,
      inputApi: asT<String>(jsonRes['inputApi']),
      inputType: inputType,
      showType: showType,
      defaultValue: asT<String>(jsonRes['defaultValue']),
      value: asT<String>(jsonRes['value']),
      webUrl: asT<String>(jsonRes['webUrl']),
      inputRegex: asT<String>(jsonRes['inputRegex']),
      selectData: selectData,
      labelWidth: asT<double>(jsonRes['labelWidth']),
      otherParam: asT<Map<String, dynamic>>(jsonRes['otherParam']),
    );
  }

  Map<String, dynamic> toJson() => <String, dynamic>{
        'fieldName': fieldName,
        'name': name,
        'notes': notes,
        'required': required,
        'accessMode': BaseTransformUtil.enumToString(accessMode),
        'inputApi': inputApi,
        'inputType': BaseTransformUtil.enumToString(inputType),
        'showType': BaseTransformUtil.enumToString(showType),
        'defaultValue': defaultValue,
        'value': value,
        'webUrl': webUrl,
        'inputRegex': inputRegex,
        'selectData': selectData,
        'labelWidth': labelWidth,
        'otherParam': otherParam,
      };

  @override
  String toString() {
    return json.encode(this);
  }
}
